package org.example.string;

import java.lang.constant.Constable;
import java.lang.invoke.MethodHandles;
import java.util.*;
import java.util.function.Function;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Demo1 {
    public static void main(String[] args) {
//        test1();
//        test2();
//        test3();
//        test4();
//        test5();
//        test6();
//        test7();
//        test8();
//        test9();
//        test10();
//        test11();
//        test12();
//        test13();
//        test14();
//        test15();
//        test16();
//        test17();
//        test18();
//        test19();
//        test20();
//        test21();
//        test22();
        test23();
    }

    private static void test23() {
        String s = "Hello";
        System.out.println(s.resolveConstantDesc(MethodHandles.lookup()));
    }

    private static void test22() {
        String constant = "Hello";
        Optional<String> description = constant.describeConstable();
        description.ifPresent(System.out::println); // Hello
    }

    private static void test21() {
        String s1 = new String("hello");
        String s2 = "hello";
        String s3 = s1.intern();
        System.out.println(s1 == s2); // false，因为s1是一个新的String对象
        System.out.println(s2 == s3); // true，因为s2和s3引用的是字符串池中的同一个对象
    }

    private static void test20() {
        Date date = new Date();
        //H的使用
        System.out.printf("2位数字24时制的小时:%tH%n", date);   // 2位数字24时制的小时:19
        //I的使用
        System.out.printf("2位数字12时制的小时:%tI%n", date);   // 2位数字12时制的小时:07
        //k的使用
        System.out.printf("2位数字24时制的小时:%tk%n", date);   // 2位数字24时制的小时:19
        //l的使用
        System.out.printf("2位数字12时制的小时:%tl%n", date);   // 2位数字12时制的小时:7
        //M的使用
        System.out.printf("2位数字的分钟:%tM%n", date);   // 2位数字的分钟:53
        //S的使用
        System.out.printf("2位数字的秒:%tS%n", date);   // 2位数字的秒:45
        //L的使用
        System.out.printf("3位数字的毫秒:%tL%n", date);   // 3位数字的毫秒:152
        //N的使用
        System.out.printf("9位数字的毫秒数:%tN%n", date);   // 9位数字的毫秒数:152000000
        //p的使用
        System.out.printf(Locale.US, "小写字母的上午或下午标记(英)：%tp%n", date);   // 小写字母的上午或下午标记(英)：pm
        System.out.printf("小写字母的上午或下午标记（中）：%tp%n", date);   // 小写字母的上午或下午标记（中）：下午
        //z的使用
        System.out.printf("相对于GMT的RFC822时区的偏移量:%tz%n", date);   // 相对于GMT的RFC822时区的偏移量:+0800
        //Z的使用
        System.out.printf("时区缩写字符串:%tZ%n", date);   // 时区缩写字符串:CST
        //s的使用
        System.out.printf("1970-1-1 00:00:00 到现在所经过的秒数：%ts%n", date);   // 1970-1-1 00:00:00 到现在所经过的秒数：1707998025
        //Q的使用
        System.out.printf("1970-1-1 00:00:00 到现在所经过的毫秒数：%tQ%n", date);   // 1970-1-1 00:00:00 到现在所经过的毫秒数：1707998025152
    }

    private static void test19() {
        Date date = new Date();
        //b的使用，月份简称
        System.out.printf(Locale.US, "英文月份简称：%tb%n", date);    // 英文月份简称：Feb
        System.out.printf("本地月份简称：%tb%n", date);    // 本地月份简称：2月
        //B的使用，月份全称
        System.out.printf(Locale.US, "英文月份全称：%tB%n", date); // 英文月份全称：February
        System.out.printf("本地月份全称：%tB%n", date);    // 本地月份全称：二月
        //a的使用，星期简称
        System.out.printf(Locale.US, "英文星期的简称：%ta%n", date);    // 英文星期的简称：Thu
        //A的使用，星期全称
        System.out.printf("本地星期的简称：%tA%n", date);   // 本地星期的简称：星期四
        //C的使用，年前两位
        System.out.printf("年的前两位数字（不足两位前面补0）：%tC%n", date); // 年的前两位数字（不足两位前面补0）：20
        //y的使用，年后两位
        System.out.printf("年的后两位数字（不足两位前面补0）：%ty%n", date); // 年的后两位数字（不足两位前面补0）：24
        //j的使用，一年的天数
        System.out.printf("一年中的天数（即年的第几天）：%tj%n", date);    // 一年中的天数（即年的第几天）：046
        //m的使用，月份
        System.out.printf("两位数字的月份（不足两位前面补0）：%tm%n", date); // 两位数字的月份（不足两位前面补0）：02
        //d的使用，日（二位，不够补零）
        System.out.printf("两位数字的日（不足两位前面补0）：%td%n", date);  // 两位数字的日（不足两位前面补0）：15
        //e的使用，日（一位不补零）
        System.out.printf("月份的日（前面不补0）：%te%n", date);   // 月份的日（前面不补0）：15
    }

    private static void test18() {
        Date date = new Date();
        //c的使用
        System.out.printf("全部日期和时间信息：%tc%n", date); // 全部日期和时间信息：周四 2月 15 19:22:50 CST 2024
        //f的使用
        System.out.printf("年-月-日格式：%tF%n", date);   // 年-月-日格式：2024-02-15
        //d的使用
        System.out.printf("月/日/年格式：%tD%n", date);   // 月/日/年格式：02/15/24
        //r的使用
        System.out.printf("HH:MM:SS PM格式（12时制）：%tr%n", date);   // HH:MM:SS PM格式（12时制）：07:22:50 下午
        //t的使用
        System.out.printf("HH:MM:SS格式（24时制）：%tT%n", date);  // HH:MM:SS格式（24时制）：19:22:50
        //R的使用
        System.out.printf("HH:MM格式（24时制）：%tR", date);   // HH:MM格式（24时制）：19:22
    }

    private static void test17() {
        //$使用
        System.out.printf("格式参数$的使用：%2$s,%1$d%n", 99, "abc");   // 格式参数$的使用：abc,99
        // -
        System.out.printf("|%-5d|%n", 15);    // |15   |
        // #
        System.out.printf("%#x%n", 99); // 0x63
        System.out.printf("%#o%n", 99); // 0143
        System.out.printf("%#a%n", 99.99); // 0x1.8ff5c28f5c28fp6
        System.out.printf("%#e%n", 99.99); // 9.999000e+01
        System.out.printf("%#f%n", 99.99); // 99.990000
        // (
        System.out.printf("%(f%n", -99.99); // (99.990000)
        //+使用
        System.out.printf("显示正负数的符号：%+d与%d%n", 99, -99);    // 显示正负数的符号：+99与-99
        //补O使用
        System.out.printf("最牛的编号是：%03d%n", 7);  // 最牛的编号是：007
        //空格使用
        System.out.printf("Tab键的效果是：% 8d%n", 7);    // Tab键的效果是：       7
        System.out.printf("Tab键的效果是：%8d%n", 7);     // Tab键的效果是：       7
        //.使用
        System.out.printf("整数分组的效果是：%,d%n", 9989997);   // 整数分组的效果是：9,989,997
        //空格和小数点后面个数
        System.out.printf("一本书的价格是：% 50.5f元%n", 49.8);  // 一本书的价格是：                                          49.80000元
        // <
        System.out.printf("%f和%<3.2f", 99.45);  // 99.450000和99.45
        // 长度
        System.out.printf("|%8d|%n", 7);     // |       7|
        System.out.printf("|%8s|%n", "123");     // |     123|
        System.out.printf("|%8c|%n", 's');     // |       s|
        System.out.printf("|%8b|%n", false);     // |   false|
        // 综合
        System.out.printf("|%1$,-10.1f|和|%<010.2f|%n", 99999.45);
        System.out.printf("|%1$,(+-10.1f|和|%,<010.2f|%n", 99999.45);
    }

    private static void test16() {
        System.out.printf("Hi,%s:%s.%s%n", "王南", "王力", "王张");   // Hi,王南:王力.王张
        System.out.printf("字母a的大写是：%c%n", 'A'); // 字母a的大写是：A
        System.out.printf("3>7的结果是：%b%n", 3 > 7);   // 3>7的结果是：false
        System.out.printf("100的一半是：%d%n", 100 / 2); // 100的一半是：50
        System.out.printf("100的16进制数是：%x%n", 100);  // 100的16进制数是：64
        System.out.printf("100的8进制数是：%o%n", 100);   // 100的8进制数是：144
        System.out.printf("50元的书打8.5折扣是：%f元%n", 50 * 0.85); // 50元的书打8.5折扣是：42.500000元
        System.out.printf("上面价格的16进制数是：%a%n", 50 * 0.85);   // 上面价格的16进制数是：0x1.54p5
        System.out.printf("上面价格的指数表示：%e%n", 50 * 0.85); // 上面价格的指数表示：4.250000e+01
        System.out.printf("%g%n", 123.456789); // 123.457
        System.out.printf("%g%n", 0.0000123456); // 1.23456e-05
        System.out.printf("%g%n", 123.0);        // 123.000
        System.out.printf("%g%n", 123456.0); // 123456
        System.out.printf("上面的折扣是%d%%%n", 85);  // 上面的折扣是85%
        System.out.printf("字母A的哈希值是：%h%n", 'A');    // 字母A的哈希值是：41
    }

    private static void test15() {
        char c = '你';
        System.out.println((int) c);    // 20320
        String s = "你好";
        System.out.println(s.length()); // 2
        char cc[] = new char[s.length()];
        s.getChars(0, s.length(), cc, 0);
        System.out.println(Arrays.toString(cc));    // [你, 好]
        System.out.println(Arrays.toString(s.chars().toArray()));   // [20320, 22909]
        System.out.println(Arrays.toString(s.codePoints().toArray()));  // [20320, 22909]

        char[] chars1 = new char[]{'\uD83D', '\uDE00'};
        String s1 = new String(chars1);
        System.out.println(s1.length());    // 2
        char cc1[] = new char[s1.length()];
        s1.getChars(0, s1.length(), cc1, 0);
        System.out.println(Arrays.toString(cc1));   // [?, ?]
        System.out.println(Arrays.toString(s1.chars().toArray()));  //  [55357, 56832]
        System.out.println(Arrays.toString(s1.codePoints().toArray())); // [128512]
    }

    private static void test14() {
        String s = "123123";
        System.out.println(s.transform((Function<CharSequence, String>) s1 -> s1 + "asdas"));
        System.out.println((String) s.transform(s1 -> s1 + "asdas"));
        // 123123asdas
    }

    private static void test13() {
        String s = "Hello\\nWorld!";
        System.out.println(s);
        System.out.println(s.translateEscapes());
        /*
        Hello\nWorld!
        Hello
        World!
         */
    }

    private static void test12() {
        String html = """
                <html>
                    <body>
                        <p>Hello, world</p>
                    </body>
                </html>
                """;
        System.out.println(html.stripIndent());

        String html1 = """
                      <html>
                          <body>
                              <p>Hello, world</p>
                          </body>
                      </html>
                """;
        System.out.println(html1.stripIndent());
    }

    private static void test11() {
        Stream<String> lines = "\n1231\r\nasdbdr\rvs1123e".lines();
        System.out.println(Arrays.toString(lines.toArray()));   // [, 1231, asdbdr, vs1123e]
    }

    private static void test10() {
        System.out.println("".isEmpty());   // true
        System.out.println("".isBlank());   // true
        System.out.println("  \t".isEmpty());   // false
        System.out.println("  \t".isBlank());   // true
    }

    private static void test9() {
        String s = "123 \t";
        System.out.println(s.trim());   // 123
        System.out.println(s.trim() == s);  // false
        System.out.println(s.strip());  // 123
        System.out.println(s.strip() == s); // false
        String s1 = "123";
        System.out.println(s1.trim());  // 123
        System.out.println(s1.trim() == s1);    // true
        System.out.println(s1.strip()); // 123
        System.out.println(s1.strip() == s1);   // true
    }

    private static void test8() {
        System.out.println(String.join("-", "123", null, "3231"));  // 123-null-3231
        System.out.println(String.join("-", "123"));                // 123
        System.out.println(String.join("-", "123") == "123");       // false
        System.out.println(String.join("-", Set.of("123", "321")));           // 321-123
    }

    private static void test7() {
        String s = "boo:and:foo";
        System.out.println(Arrays.toString(s.split(":", 2)));   // [boo, and:foo]  limit为2，最多分隔2次
        System.out.println(Arrays.toString(s.split(":", 5)));    // [boo, and, foo] limit为5，但分隔2次就结束了
        System.out.println(Arrays.toString(s.split(":", 0)));    // [boo, and, foo] limit为0。分隔完为止
        System.out.println(Arrays.toString(s.split(":", -1)));   // [boo, and, foo] 在结尾没有空字符串情况下，和0一样
        System.out.println(Arrays.toString(s.split("o", 6)));    // [b, , :and:f, , ] limit为6，但分隔4次就结束了，结尾保留空字符串
        System.out.println(Arrays.toString(s.split("o", -2)));   // [b, , :and:f, , ] 后边类似
        System.out.println(Arrays.toString(s.split("o", 0)));    // [b, , :and:f]
    }

    private static void test6() {
        String s = "aaa";
        String replace = s.replaceFirst("aa", "a");
        System.out.println(replace);    // aa
        System.out.println(replace == s);   // false
        System.out.println(s.replaceFirst("cc", "a") == s);   // true

        replace = s.replaceAll("aa", "a");
        System.out.println(replace);    // aa
        System.out.println(replace == s);   // false
        System.out.println(s.replaceAll("cc", "a") == s);   // true

        replace = s.replace("aa", "a");
        System.out.println(replace);    // aa
        System.out.println(replace == s);   // false
        System.out.println(s.replace("cc", "a") == s);  // true

        System.out.println("asd\\asd$1".replaceFirst("$1", "\ta")); // asd\asd$1
        System.out.println("asd\\asd$1".replaceAll("$1", "\ta"));   // asd\asd$1
        System.out.println("asd\\asd$1".replace("$1", "\ta"));      // asd\asd a
    }

    private static void test5() {
        String s = "123455";
        String s1 = s.replace('1', '7');
        String s2 = s.replace('7', '9');
        System.out.println(s == s1);    // false
        System.out.println(s == s2);    // true
    }

    private static void test4() {
        String s = "123";
        String s1 = "3445";
        String concat = s.concat(s1);
        System.out.println(concat == s);    // false
        System.out.println(concat == s1);   // false
        String s2 = "";
        concat = s.concat(s2);
        System.out.println(concat == s);    // true
        System.out.println(concat == s2);   // false
    }

    private static void test3() {
        String a = "abc";
        String b = "abcd";
        System.out.println(a.compareTo(b)); // -1
        String c = "a";
        String d = "A";
        System.out.println(c.compareTo(d)); // 32
        String e = "b";
        System.out.println(c.compareTo(e)); // -1
    }

    private static void test2() {
        //构造方法的方式得到对象
        char[] chs = {'a', 'b', 'c'};
        String s1 = new String(chs);
        String s2 = new String(chs);
        //直接赋值的方式得到对象
        String s3 = "abc";
        String s4 = "abc";

        //比较字符串对象地址是否相同
        System.out.println(s1 == s2);   // false
        System.out.println(s3 == s4);   // true
        System.out.println(s1 == s3);   // false
        System.out.println("--------");
        //比较字符串内容是否相同
        System.out.println(s1.equals(s2));   // true
        System.out.println(s3.equals(s4));   // true
        System.out.println(s1.equals(s3));   // true
    }

    private static void test1() {
        // public String()：创建一个空白字符串对象，不含有任何内容
        String s1 = new String();
        System.out.println("s1:" + s1); // s1:

        // public String(char[] chs)：根据字符数组的内容，来创建字符串对象
        char[] chs = {'a', 'b', 'c'};
        String s2 = new String(chs);
        System.out.println("s2:" + s2); // s2:abc

        // public String(byte[] bys)：根据字节数组的内容，来创建字符串对象
        byte[] bys = {97, 98, 99};
        String s3 = new String(bys);
        System.out.println("s3:" + s3); // s3:abc

        // String s = “abc”;	直接赋值的方式创建字符串对象，内容就是abc
        String s4 = "abc";
        System.out.println("s4:" + s4); // s4:abc
    }
}
